using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace rocketjump
{
    public class PlayerSprite : Sprite
    {
        Texture2D head;
        Texture2D torso;
        Texture2D sledge;
        Texture2D rockets;
        Texture2D smoke;
        Texture2D dust;
        Texture2D explosion;

        List<Vector2> slope_vector;
        public bool launched = false;
        public bool crashed = false;
        public bool exploded = false;

        float totalElapsed;
        float totalElapsedExplosion;
        float totalElapsedDust;

        float timePerRocketFrame;
        public int rocketFrame;
        int rocketFrameCount;

        int timesExploded = 0;
        float timePerExplosionFrame;
        int explosionAmount = 10;

        public int [] explosionFrame;
        int explosionFrameCount;
        Vector2 [] explosionPosition;

        float timePerDustFrame;
        public int dustFrame;
        int dustFrameCount;

        public float maxSpeed = 1500;
        public Vector2 velocity = Vector2.Zero;

        List<Texture2D> rocketEmitterTextures;
        ParticleEngine rocketEmitter;

        public float TrickTimeCounter = 0;
        public String TrickName;
        Texture2D TrickTexture;
        SpriteEffects TrickEffect;

        Random random;

        public PlayerSprite()
        {
            random = new Random();

            position = new Vector2(280, 350);
            slope_vector = new List<Vector2>();
            torso = GraphicsHelper.LoadTexture("graphics\\player\\char-body");
            head = GraphicsHelper.LoadTexture("graphics\\player\\char-head");
            rockets = GraphicsHelper.LoadTexture("graphics\\player\\rocket-134");
            sledge = GraphicsHelper.LoadTexture("graphics\\player\\sledge");
            smoke = GraphicsHelper.LoadTexture("graphics\\effects\\debugParticle");
            dust = GraphicsHelper.LoadTexture("graphics\\effects\\anim_dustcloud_240");
            explosion = GraphicsHelper.LoadTexture("graphics\\effects\\anim_expl_64");

            totalElapsed = 0;
            timePerRocketFrame = 0.05f;
            rocketFrame = 0;
            rocketFrameCount = 3;

            totalElapsedExplosion = 0;
            timePerExplosionFrame = 0.10f;
            explosionFrame = new int[explosionAmount];
            explosionFrameCount = 6;

            totalElapsedDust = 0;
            timePerDustFrame = 0.05f;
            dustFrame = 0;
            dustFrameCount = 8;

            explosionPosition = new Vector2[explosionAmount];

            rocketEmitterTextures = new List<Texture2D>();
            rocketEmitterTextures.Add(smoke);
            rocketEmitter = new ParticleEngine(rocketEmitterTextures, new Vector2(0, 0), 9, 0.3f, 55, 1);

        }

        public void DoTrick()
        {

            Random rand = new Random();

            //clear fake randoms
            rand.Next();
            rand.Next();
            rand.Next();
            rand.Next();

            TrickTimeCounter = 1.5f;

            int trickID = rand.Next(1,11);

            switch (trickID)
            {
                case 1:
                    TrickName = "THE NOT A ZOOLOGIST";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick1");
                    TrickEffect = SpriteEffects.None;
                    break;
                case 2:
                    TrickName = "THE NOT ON MY PLANE!";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick2");
                    TrickEffect = SpriteEffects.None;
                    break;
                case 3:
                    TrickName = "THE GODDAMN SHARK?!";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick3");
                    TrickEffect = SpriteEffects.None;
                    break;
                case 4:
                    TrickName = "THE ABSOLUTELY, POSITIVELY";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick4");
                    TrickEffect = SpriteEffects.None;
                    break;
                case 5:
                    TrickName = "THE ARROW IN THE KNEE";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick5");
                    TrickEffect = SpriteEffects.None;
                    break;
                case 6:
                    TrickName = "THE ENGLISH, &@$!#%$#";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick2");
                    TrickEffect = SpriteEffects.FlipVertically;
                    break;
                case 7:
                    TrickName = "THE MAY BE DUMB #&@";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick3");
                    TrickEffect = SpriteEffects.FlipVertically;
                    break;
                case 8:
                    TrickName = "THE GOODWILL WINDMILL";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick6");
                    TrickEffect = SpriteEffects.FlipHorizontally;
                    break;
                case 9:
                    TrickName = "THE SPIDER REACTOR";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick7");
                    TrickEffect = SpriteEffects.None;
                    break;
                case 10:
                    TrickName = "THE KNEE DRIVER";
                    TrickTexture = GraphicsHelper.LoadTexture("graphics\\player\\trick7");
                    TrickEffect = SpriteEffects.FlipVertically;
                    break;
            }
        }

        public override void Update(float tdelta)
        {
            base.Update(tdelta);

            if (TrickTimeCounter > 0)
                TrickTimeCounter -= tdelta;

            //On the track
            if (slope_vector.Count > 0 && !crashed)
            {
                Vector2 target = slope_vector[0];

                velocity = target - position;
                velocity.Normalize();
                velocity *= maxSpeed;
                Vector2 distance = target - position;
                float f = (tdelta * maxSpeed) / distance.Length();
                position = Vector2.Lerp(position, target, f);

                if ((target - position).Length() < tdelta * maxSpeed)
                {
                    slope_vector.RemoveAt(0);
                }
                //rotation = GraphicsHelper.GetAngle(distance);
                float targetangle = GraphicsHelper.GetAngle(distance);
                rotation = rotation * 0.80f + targetangle * 0.20f;
            } 
            else if(launched && !crashed)
            {
                if (position.Y < 400 && !crashed)
                {
                    position += velocity * tdelta;
                    velocity.Y += tdelta * maxSpeed / 6;
                    velocity.X = maxSpeed;
                        
                        /*new Vector2(0, tdelta * maxSpeed / 5);
                    velocity.Normalize();
                    velocity *= maxSpeed;*/
                }
                else
                {
                    //position += velocity * tdelta;
                    //this.launched = false;
                    this.crashed = true;
                    for (int i = 0; i < explosionAmount; i++)
                    {
                        explosionFrame[i] = random.Next(explosionFrameCount);
                    }
                    switch(random.Next(1, 5)) 
                    {
                        case 1:
                            SoundHelper.PlaySound("sounds\\playerhitground");
                            break;
                        case 2:
                            SoundHelper.PlaySound("sounds\\playerhitground2");
                            break;
                        case 3:
                            SoundHelper.PlaySound("sounds\\hit3");
                            break;
                        case 4:
                            SoundHelper.PlaySound("sounds\\hit4");
                            break;
                    }
                }

                rotation = GraphicsHelper.GetAngle(velocity);
            }
        }
        //280,320 on alotus
        //490,330
        //560,310
        //620,280
        //690,210
        public bool StartRockets()
        {
            if (slope_vector.Count > 0 || launched)
                return false;

            SoundHelper.PlaySound("sounds\\rocketstart2");
            launched = true;
            slope_vector.Add(new Vector2(490,350));
            slope_vector.Add(new Vector2(560, 350));
            slope_vector.Add(new Vector2(678, 317));
            slope_vector.Add(new Vector2(770,270));
            slope_vector.Add(new Vector2(840, 210));
            slope_vector.Add(new Vector2(898, 148));

            return true;
        }

        public override void Draw(Camera cam)
        {
            if (!exploded)
            {
                Vector2 rotVector = Vector2.Zero;

                if (TrickTimeCounter > 0)
                {
                    rotVector.Y -= TrickTexture.Height /2.0f - 60;
                    rotVector = GraphicsHelper.InterpolateVector(rotVector, rotation);
                    rotVector += position - (cam.Position - (cam.viewPort / 2));
                    GraphicsHelper.Draw(TrickTexture, rotVector, 1, rotation, TrickEffect);
                }
                else
                {
                    rotVector = Vector2.Zero;
                    rotVector.Y += 16.0f;
                    rotVector.X += 30.0f;
                    rotVector = GraphicsHelper.InterpolateVector(rotVector, rotation);
                    rotVector += position - (cam.Position - (cam.viewPort / 2));
                    GraphicsHelper.Draw(torso, rotVector, 1, rotation);

                    rotVector = Vector2.Zero;
                    rotVector.Y -= torso.Height / 2 + head.Height / 2;
                    rotVector.Y += 25.0f;
                    rotVector.X += 30.0f;
                    rotVector = GraphicsHelper.InterpolateVector(rotVector, rotation);
                    rotVector += position - (cam.Position - (cam.viewPort / 2));
                    GraphicsHelper.Draw(head, rotVector, 1, rotation);
                }
                rotVector = Vector2.Zero;
                rotVector.X -= 24;
                rotVector.Y += torso.Height / 2;
                rotVector = GraphicsHelper.InterpolateVector(rotVector, rotation);
                rotVector += position - (cam.Position - (cam.viewPort / 2));
                GraphicsHelper.Draw(sledge, rotVector, 1, rotation);

                rotVector = Vector2.Zero;
                rotVector.X -= 130.0f;
                rotVector.Y += 60.0f;
                rotVector = GraphicsHelper.InterpolateVector(rotVector, rotation);
                rotVector += position - (cam.Position - (cam.viewPort / 2));
                rocketEmitter.EmitterLocation = rotVector;
                GraphicsHelper.DrawParticleEmitter(rocketEmitter);
                
                rotVector = Vector2.Zero;
                rotVector.X -= 90.0f;
                rotVector.Y += 61.0f;
                rotVector = GraphicsHelper.InterpolateVector(rotVector, rotation);
                rotVector += position - (cam.Position - (cam.viewPort / 2));
                GraphicsHelper.DrawFrameHorizontal(rockets, rotVector, 1, rotation, rocketFrame, rocketFrameCount);
            }

            if (crashed)
            {
                rocketFrame = 0;
                if (!exploded)
                {

                    for (int i = 0; i < explosionAmount; i++)
                    {
                        GraphicsHelper.DrawFrameHorizontal(explosion, explosionPosition[i], 2.0f, i * 360 / explosionAmount, explosionFrame[i], 7);
                    }
                }
                else
                {
                    // Reset the jump
                    GraphicsHelper.DrawFrameHorizontal(dust, new Vector2(cam.viewPort.X / 2 + 200, cam.viewPort.Y + 100), 2, 0, dustFrame, 8);
                    timesExploded = 0;
                }   
            }
        }

        public void UpdateRockets(float elapsed, Camera cam)
        {
            rocketEmitter.Update();

            if (!launched && !crashed)
            {                    
                int spread = 150;
                for (int i = 0; i < explosionAmount; i++)
                {
                    explosionPosition[i] = new Vector2(cam.viewPort.X / 2 +spread / 2 - random.Next(spread), cam.viewPort.Y+spread / 2 - random.Next(spread));
                }
                rocketFrame = 0;
                rocketEmitter.Stop();
                return;
            }
            else if (launched && !crashed)
            {
                rocketEmitter.Start();
                totalElapsed += elapsed;
                if (totalElapsed > timePerRocketFrame)
                {
                    rocketFrame++;
                    rocketFrame = rocketFrame % rocketFrameCount;
                    totalElapsed -= timePerRocketFrame;
                }
            }
            else if (crashed)
            {
                if (!exploded)
                    AnimateExplosions(this.position, elapsed);
                else if (exploded) 
                    AnimateDustcloud(this.position, elapsed);
            }
        }

        private void AnimateExplosions(Vector2 position, float elapsed)
        {
            for (int i = 0; i < explosionAmount; i++)
            {

                if (timesExploded < 5*explosionAmount)
                {
                    totalElapsedExplosion += elapsed;
                    if (totalElapsedExplosion > timePerExplosionFrame && explosionFrame[i] < explosionFrameCount)
                    {
                        explosionFrame[i]++;
                        totalElapsedExplosion -= timePerExplosionFrame;
                    }
                    else if (totalElapsedExplosion > timePerExplosionFrame)
                    {
                        explosionPosition[i] = new Vector2(explosionPosition[i].X + random.Next(-30, 30), explosionPosition[i].Y + random.Next(-30, 30));
                        explosionFrame[i] = 0;
                        totalElapsedExplosion -= timePerExplosionFrame;
                        timesExploded++;

                        SoundHelper.PlaySound("sounds\\playerexplosion"+random.Next(1,6));
                    }
                }
                else
                {
                    explosionFrame[i] = 0;
                    exploded = true;
                    SoundHelper.StopMusic();
                    JumpGame.jumpOver = true;
                }
            }
        }

        private void AnimateDustcloud(Vector2 position, float elapsed)
        {
            totalElapsedDust += elapsed;
            if (totalElapsedDust > timePerDustFrame && dustFrame < dustFrameCount)
            {
                dustFrame++;
                totalElapsedDust -= timePerDustFrame;
            }
        }
    }
}
